﻿using System;
using System.Collections.Generic;
using System.Configuration.Provider;
using System.Linq;
using Opo.Net.Mail;

namespace Opo.Perspective.Core
{
    /// <summary>
    /// Represents a cache that stores mail messages
    /// </summary>
    public abstract class MailCache : IRepository<Message>
    {
        IMailStore _mailStore;
        IPerspectivePipeline<IPerspectiveEntity> _pipeline;

        /// <summary>
        /// Initializes a new instance of the <see cref="MailCache"/> class.
        /// </summary>
        /// <param name="mailStore">The mail store.</param>
        public MailCache(IMailStore mailStore, IPerspectivePipeline<IPerspectiveEntity> pipeline)
        {
            if (mailStore == null)
            {
                throw new ArgumentNullException("mailStore");
            }
            if (pipeline == null)
            {
                throw new ArgumentNullException("pipeline");
            }
            _mailStore = mailStore;
            _pipeline = pipeline;
        }

        /// <summary>
        /// Adds the specified message to the mail cache.
        /// </summary>
        /// <param name="entity">The message.</param>
        /// <returns></returns>
        public abstract Message Add(Message message);
        /// <summary>
        /// Gets the item with the specified MessageID.
        /// </summary>
        /// <param name="id">The message id.</param>
        /// <returns></returns>
        public abstract Message Get(Guid id);
        /// <summary>
        /// Gets all mail messages in the cache.
        /// </summary>
        /// <returns></returns>
        public abstract IEnumerable<Message> GetAll();
        /// <summary>
        /// Updates the specified message.
        /// </summary>
        /// <param name="message">The message.</param>
        /// <returns></returns>
        public abstract Message Update(Message message);
        /// <summary>
        /// Deletes the specified messsage.
        /// </summary>
        /// <param name="messsage">The messsage.</param>
        public abstract void Delete(Message messsage);

        /// <summary>
        /// Updates the mail cache, respectively gets all new messages from the mail store.
        /// </summary>
        public void UpdateMailCache()
        {
            List<IMailMessage> newMessages = _mailStore.GetNewMessages(GetExistingMessageIDs()).ToList();
            foreach (IMailMessage message in newMessages)
            {
                Message m = (Message)message;
                _pipeline.Process(m);
                Add(m);
            }
        }

        /// <summary>
        /// Gets the messageIDs of all messages in the mail cache
        /// </summary>
        /// <returns></returns>
        internal abstract IEnumerable<string> GetExistingMessageIDs();
    }
}
